<!doctype html>
<meta charset="utf-8" />
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="resources/copy-data-transfer.js"></script>
<style>
#dropwrapper {
  display: block;
  width: 400px;
  height: 200px;
  position: relative;
  padding: 50px 0 0 100px;
}
#dropzone {
  display: block;
  border: 1px solid black;
  width: 200px;
  height: 100px;
}
</style>

<p>
  Please download <a download href="resources/dragged-file.txt">this file</a>,
  and drag it into the box below.
</p>

<div id="dropwrapper">
  <div id="dropzone">
    Drop Here
  </div>
</div>

<script>
'use strict';

const dropWrapper = document.querySelector('#dropwrapper');
const dropZone = document.querySelector('#dropzone');

const dragEnterPromise = new Promise((resolve, reject) => {
  // Needed to keep the drag-and-drop going.
  dropWrapper.ondragenter = event => event.preventDefault();

  dropZone.ondragenter = event => {
    event.preventDefault();  // Needed to keep the drag-and-drop going.
    resolve(copyDataTransfer(event.dataTransfer));
  };
});
const dragOverPromise = new Promise((resolve, reject) => {
  // Needed to keep the drag-and-drop going.
  dropZone.ondragover = event => event.preventDefault();

  dropWrapper.ondragover = event => {
    event.preventDefault();  // Needed to keep the drag-and-drop going.
    resolve(copyDataTransfer(event.dataTransfer));
  };
});
const dragLeavePromise = new Promise((resolve, reject) => {
  dropWrapper.ondragleave = event => {
    resolve(copyDataTransfer(event.dataTransfer));
  };
});
const dropPromise = new Promise((resolve, reject) => {
  dropZone.ondrop = event => {
    event.preventDefault();  // Needed to prevent drop navigation.
    resolve(copyDataTransfer(event.dataTransfer));
  };
});

const wrapperRect = dropWrapper.getBoundingClientRect();
const dropRect = dropZone.getBoundingClientRect();
if (window.eventSender) {
  eventSender.mouseMoveTo(0, 0);
  eventSender.beginDragWithFiles(['resources/dragged-file.txt']);

  // dragenter + dragover on #dropwrapper
  const wrapperX = wrapperRect.left + 10;
  const wrapperY = wrapperRect.top + 10;
  eventSender.mouseMoveTo(wrapperX, wrapperY);

  // dragleave on #dropwrapper and dragenter + dragover + dragleave on #dropzone
  setTimeout(() => {
    const centerX = (dropRect.left + dropRect.right) / 2;
    const centerY = (dropRect.top + dropRect.bottom) / 2;
    eventSender.mouseMoveTo(centerX, centerY);
    eventSender.mouseUp();
  }, 0);
}

promise_test(() => {
  return dragEnterPromise.then((dataTransfer) => {
    assert_array_equals(dataTransfer.types, ['Files']);
  });
}, 'DataTransfer.types in dragenter');

promise_test(() => {
  return dragOverPromise.then((dataTransfer) => {
    assert_array_equals(dataTransfer.types, ['Files']);
  });
}, 'DataTransfer.types in dragover');

promise_test(() => {
  return dragLeavePromise.then((dataTransfer) => {
    assert_array_equals(dataTransfer.types, ['Files']);
  });
}, 'DataTransfer.types in dragleave');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_array_equals(dataTransfer.types, ['Files']);
  });
}, 'DataTransfer.types in drop');

promise_test(() => {
  return dragEnterPromise.then((dataTransfer) => {
    assert_object_equals(dataTransfer.data, {Files: ''});
  });
}, 'DataTransfer.getData() return values in dragenter');

promise_test(() => {
  return dragOverPromise.then((dataTransfer) => {
    assert_object_equals(dataTransfer.data, {Files: ''});
  });
}, 'DataTransfer.getData() return values in dragover');

promise_test(() => {
  return dragLeavePromise.then((dataTransfer) => {
    assert_object_equals(dataTransfer.data, {Files: ''});
  });
}, 'DataTransfer.getData() return values in dragleave');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_object_equals(dataTransfer.data, {Files: ''});
  });
}, 'DataTransfer.getData() return values in drop');

promise_test(() => {
  return dragEnterPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.files.length, 0,
        'DataTransfer is protected, so DataTransfer.files should be empty');
  });
}, 'DataTransfer.files in dragenter');

promise_test(() => {
  return dragOverPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.files.length, 0,
        'DataTransfer is protected, so DataTransfer.files should be empty');
  });
}, 'DataTransfer.files in dragover');

promise_test(() => {
  return dragLeavePromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.files.length, 0,
        'DataTransfer is protected, so DataTransfer.files should be empty');
  });
}, 'DataTransfer.files in dragleave');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.files.length, 1,
        'DataTransfer.files should have one element');
    const file = dataTransfer.files[0];
    assert_equals(file.file.name, 'dragged-file.txt');
    assert_equals(file.file.type, 'text/plain');
    assert_equals(file.file.size, 21);
    assert_equals(file.data, 'The test has FAILED.\n');
  });
}, 'DataTransfer.files in drop');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    const file = dataTransfer.files[0].file;
    assert_true(
        file instanceof File,
        'DataTransfer.files[0] should be a File instance');
    assert_equals(
        file.name, 'dragged-file.txt',
        "File.name should reflect the dropped file's name");
    assert_equals(
        file.type, 'text/plain',
        "File.type should reflect the dropped file's MIME type");
    assert_equals(
        file.size, 21,
        "File.type should reflect the dropped file's size");
  });
}, 'DataTransfer.files[0] File metadata in drop');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_equals(dataTransfer.files[0].data, 'The test has FAILED.\n');
  });
}, 'Using FileReader to read DataTransfer.files[0] in drop');

promise_test(() => {
  return dragEnterPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.items.length, 1,
        'DataTransfer.items should have 1 element');
    const item = dataTransfer.items[0];
    assert_equals(
        item.kind, 'file',
        'DataTransferItem.kind should indicate that a file was dropped');
    assert_equals(
        item.type, 'text/plain',  // Firefox returns application/x-moz-file.
        "DataTransferItem.type should reflect the dropped file's MIME type");
    assert_equals(
        item.file, null,  // Firefox returns the file's metadata.
        'DataTransferItem.getAsFile() should reflect that the DataTransfer ' +
        'is protected');
  });
}, 'DataTransfer.items in dragenter');

promise_test(() => {
  return dragOverPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.items.length, 1,
        'DataTransfer.items should have 1 element');
    const item = dataTransfer.items[0];
    assert_equals(
        item.kind, 'file',
        'DataTransferItem.kind should indicate that a file was dropped');
    assert_equals(
        item.type, 'text/plain',  // Firefox returns application/x-moz-file.
        "DataTransferItem.type should reflect the dropped file's MIME type");
    assert_equals(
        item.file, null,  // Firefox returns the file's metadata.
        'DataTransferItem.getAsFile() should reflect that the DataTransfer ' +
        'is protected');
  });
}, 'DataTransfer.items in dragover');

promise_test(() => {
  return dragLeavePromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.items.length, 1,
        'DataTransfer.items should have 1 element');
    const item = dataTransfer.items[0];
    assert_equals(
        item.kind, 'file',
        'DataTransferItem.kind should indicate that a file was dropped');
    assert_equals(
        item.type, 'text/plain',  // Firefox returns application/x-moz-file.
        "DataTransferItem.type should reflect the dropped file's MIME type");
    assert_equals(
        item.file, null,  // Firefox returns the file's metadata.
        'DataTransferItem.getAsFile() should reflect that the DataTransfer ' +
        'is protected');
  });
}, 'DataTransfer.items in dragleave');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.items.length, 1,
        'DataTransfer.items should have 1 element');
    const item = dataTransfer.items[0];
    assert_equals(
        item.kind, 'file',
        'DataTransferItem.kind should indicate that a file was dropped');
    assert_equals(
        item.type, 'text/plain',  // Firefox returns application/x-moz-file
        "DataTransferItem.type should reflect the dropped file's MIME type");
  });
}, 'DataTransfer.items in drop');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_equals(
        dataTransfer.items[0].error, undefined,
        'Reading the file in DataTransfer.items[0] should not throw');

    const file = dataTransfer.items[0].file;
    assert_true(
        file instanceof File,
        'DataTransfer.items[0].getAsFile() should return a File instance');
    assert_equals(
        file.name, 'dragged-file.txt',
        "File.name should reflect the dropped file's name");
    assert_equals(
        file.type, 'text/plain',
        "File.type should reflect the dropped file's MIME type");
    assert_equals(
        file.size, 21,
        "File.type should reflect the dropped file's size");
  });
}, 'DataTransfer.items[0].getAsFile() File metadata in drop');

promise_test(() => {
  return dropPromise.then((dataTransfer) => {
    assert_equals(dataTransfer.items[0].data, 'The test has FAILED.\n');
  });
}, 'Using FileReader to read DataTransfer.items[0].getAsFile() in drop');

</script>
